home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Megadoom II
/
MEGADOOM II - iso.7z
/
MEGADOOM II.ISO
/
doom
/
editors
/
wadfile
/
warm11
/
wadio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-21
|
25KB
|
623 lines
/******************************************************************************
MODULE: WADIO.C
WRITTEN BY: Robert Fenske, Jr. (rfenske@swri.edu)
Southwest Research Institute
Electromagnetics Division
6220 Culebra
San Antonio, Texas 78238-5166
CREATED: May 1994
DESCRIPTION: This module contains routines to read and write DOOM-
related IWAD, PWAD, and VERDA patch files.
There is a number of byte swapping calls used in the
SunOS case; these calls are ugly, but necessary since
the WAD files store data in little-endian order.
DOOM is a trademark of id Software, Inc.
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "dmglobal.i"
#if defined(sun) && !defined(BSWAP) /* anything big-endian (like */
#define BSWAP 1 /* Suns) needs bytes swapped */
#endif
#if defined(BSWAP)
#define bswapw(v) ((unsigned short)((((v)>>8)&0xFF) | ((v)<<8)))
#define bswapl(v) ((unsigned long)((((v)>>24)&0x000000FFL) | \
(((v)>> 8)&0x0000FF00L) | \
(((v)<< 8)&0x00FF0000L) | \
( (v)<<24)))
#else
#define bswapw(v) (v)
#define bswapl(v) (v)
#endif
#define is_type(n,t) (strncmp((n),mapresrc[t],sizeof(n)) == 0)
local char mapresrc[][9] = { /* resource name in dir */
"", "THINGS", "LINEDEFS", "SIDEDEFS", "VERTEXES", "SEGS",
"SSECTORS", "NODES", "SECTORS", "REJECT", "BLOCKMAP"
};
local int mapresiz[] = { /* item size in resource */
1, sizeof(DOOM_THING), sizeof(DOOM_LINE),
sizeof(DOOM_SIDE), sizeof(DOOM_VERT),
sizeof(DOOM_SEGS), sizeof(DOOM_SSECTOR),
sizeof(DOOM_NODE), sizeof(DOOM_SECTOR),
sizeof(DOOM_REJECT), sizeof(DOOM_BLOCKMAP)
};
/******************************************************************************
ROUTINE: wad_bswap(winfo,resource)
WRITTEN BY: Robert Fenske, Jr.
CREATED: May 1994
DESCRIPTION: This routine swaps the bytes in the short integer
fields of the various resources. This is necessary
since the data files store integers in Intel little-
endian order, while all real systems use big-endian
order.
******************************************************************************/
#if defined(BSWAP)
#if defined(ANSI_C)
local void wad_bswap(register WAD_INFO *winfo, int resource)
#else
local void wad_bswap(winfo,resource)
register WAD_INFO *winfo;
int resource;
#endif
{
short *data = (short *)winfo->data[resource]; /* where data is */
DOOM_SIDE *sides = (DOOM_SIDE *)data;
DOOM_SECTOR *sects = (DOOM_SECTOR *)data;
int cnt = resource_count(&winfo->dir[resource]);
int type;
register int d, w;
if (data != NULL) {
for (type = 0; type < numelm(mapresrc); type++)
if (is_type(winfo->dir[resource].name,type)) break;
switch (type) {
case THINGS:
case LINES:
case VERTS:
case SEGS:
case SSECTS:
case NODES:
case BLKMAPS:
for (d = 0; d < cnt; d++)
for (w = 0; w < mapresiz[type]/2; w++)
data[d*mapresiz[type]/2+w] = bswapw(data[d*mapresiz[type]/2+w]);
bcase SIDES: /* only swap integer fields */
for (d = 0; d < cnt; d++) {
sides[d].image_xoff = bswapw(sides[d].image_xoff);
sides[d].image_yoff = bswapw(sides[d].image_yoff);
sides[d].sectndx = bswapw(sides[d].sectndx);
}
bcase SECTS: /* only swap integer fields */
for (d = 0; d < cnt; d++) {
sects[d].floor_ht = bswapw(sects[d].floor_ht);
sects[d].ceil_ht = bswapw(sects[d].ceil_ht);
sects[d].light_lvl = bswapw(sects[d].light_lvl);
sects[d].property = bswapw(sects[d].property);
sects[d].line_tag = bswapw(sects[d].line_tag);
}
bcase REJECTS: /* don't have to swap this */
;
bdefault: /* something else--no swap */
;
}
}
}
#endif
/******************************************************************************
ROUTINE: resource_update(winfo,entry,data,count)
WRITTEN BY: Robert Fenske, Jr.
CREATED: June 1994
DESCRIPTION: This routine assigns the input data to the specified
entry. If the entry already has data, it is freed
first. The changed flag is set to TRUE.
******************************************************************************/
#if defined(ANSI_C)
void resource_update(register WAD_INFO *winfo, int entry, void *data,
long count)
#else
void resource_update(winfo,entry,data,count)
register WAD_INFO *winfo;
int entry;
void *data;
long count;
#endif
{
register int type;
if ((char *)data != winfo->data[entry]) blockfree(winfo->data[entry]);
winfo->data[entry] = (char *)data;
for (type = 0; type < numelm(mapresrc); type++)
if (is_type(winfo->dir[entry].name,type)) break;
if (type < numelm(mapresrc)) winfo->dir[entry].nbytes = count*mapresiz[type];
else winfo->dir[entry].nbytes = count;
winfo->count[entry] = count;
winfo->changed[entry] = TRUE;
}
/******************************************************************************
ROUTINE: resource_count(entry)
WRITTEN BY: Robert Fenske, Jr.
CREATED: June 1994
DESCRIPTION: This routine gets the count of the number of items in
the input directory entry (resource). If the entry
is not associated with map level data, the number of
items is simply the byte count.
******************************************************************************/
#if defined(ANSI_C)
int resource_count(register DIR_ENTRY *entry)
#else
int resource_count(entry)
register DIR_ENTRY *entry;
#endif
{
int count = 0;
register int type;
if (entry != NULL) {
for (type = 0; type < numelm(mapresrc); type++)
if (is_type(entry->name,type)) break;
if (type < numelm(mapresrc)) count = entry->nbytes/mapresiz[type];
else count = entry->nbytes;
}
return count;
}
/******************************************************************************
ROUTINE: patch_read(winfo,entry,resources_needed)
WRITTEN BY: Robert Fenske, Jr.
CREATED: May 1994
DESCRIPTION: This routine reads a VERDA patch file. It reads the
file twice; the first time is to obtain the sizes of
each of the resources. The input resources_needed is
ignored--everything in the patch file is read. Also,
only one level's data is stored in a patch file.
******************************************************************************/
#if defined(ANSI_C)
boolean patch_read(register WAD_INFO *winfo, int entry, long resources_needed)
#else
boolean patch_read(winfo,entry,resources_needed)
register WAD_INFO *winfo;
int entry;
long resources_needed;
#endif
{
char str[256];
int type;
DOOM_THING *things;
DOOM_LINE *lines;
DOOM_SIDE *sides;
DOOM_VERT *verts;
DOOM_SEGS *segs;
DOOM_SSECTOR *ssecs;
DOOM_NODE *nodes;
DOOM_SECTOR *sects;
register int k;
if (winfo->head.count <= entry) /* can't read beyond count */
return FALSE;
for (k = 0; k < ALL; k++)
winfo->count[k] = 0;
rewind(winfo->fp);
for (k = 0; fgets(str,sizeof str,winfo->fp) != NULL; ) {/* get counts */
if (str[0] == ';' || str[0] == '#') /* skip any comments */
continue;
if (k == 0) {
k = sscanf(str," %d %d %d %lf",&winfo->ep,&winfo->mp,&type,&winfo->ver);
continue;
}
k = str[0] != '%';
if (k) winfo->count[type]++;
}
for (k = 0; k < ALL; k++)
if ((resources_needed & (1L<<k)) && winfo->count[k] > 0) {
blockfree(winfo->data[k]);
winfo->dir[k].nbytes = winfo->count[k]*mapresiz[k];
winfo->data[k] = blockmem(char,winfo->dir[k].nbytes);
}
things = (DOOM_THING *)winfo->data[THINGS];
lines = (DOOM_LINE *)winfo->data[LINES];
sides = (DOOM_SIDE *)winfo->data[SIDES];
verts = (DOOM_VERT *)winfo->data[VERTS];
segs = (DOOM_SEGS *)winfo->data[SEGS];
ssecs = (DOOM_SSECTOR *)winfo->data[SSECTS];
nodes = (DOOM_NODE *)winfo->data[NODES];
sects = (DOOM_SECTOR *)winfo->data[SECTS];
rewind(winfo->fp);
for (k = 0; fgets(str,sizeof str,winfo->fp) != NULL; ) {
if (str[0] == ';' || str[0] == '#') /* skip any comments */
continue;
if (k == 0) {
k = sscanf(str," %d %d %d %lf",&winfo->ep,&winfo->mp,&type,&winfo->ver);
continue;
}
if (!(resources_needed & (1L << type)))
continue;
switch (type) {
case THINGS: /* THINGS */
sscanf(str,"%*d %4hx %4hx %3hd %4hx %4hx",
&things->x,&things->y,&things->angle,&things->item,
&things->flag);
things++;
bcase LINES: /* LINES */
sscanf(str,"%*d %4hx %4hx %4hx %4hx %4hx %4hx %4hx",
&lines->fndx,&lines->tndx,&lines->flag,&lines->action_flag,
&lines->sect_tag,&lines->rsidndx,&lines->lsidndx);
lines++;
bcase SIDES: /* SIDES */
sscanf(str,"%*d %4hx %4hx %8c %8c %8c %4hx",
&sides->image_xoff,&sides->image_yoff,
sides->lwall,sides->uwall,sides->nwall,&sides->sectndx);
while (sides->lwall[min(8,strlen(sides->lwall))-1] == ' ')
sides->lwall[min(8,strlen(sides->lwall))-1] = '\0';
while (sides->uwall[min(8,strlen(sides->uwall))-1] == ' ')
sides->uwall[min(8,strlen(sides->uwall))-1] = '\0';
while (sides->nwall[min(8,strlen(sides->nwall))-1] == ' ')
sides->nwall[min(8,strlen(sides->nwall))-1] = '\0';
sides++;
bcase VERTS: /* VERTEXES */
sscanf(str,"%*d %4hx %4hx",&verts->x,&verts->y);
verts++;
bcase SEGS: /* SEGS */
sscanf(str,"%*d %4hx %4hx %4hx %4hx %4hx %4hx",
&segs->fndx,&segs->tndx,&segs->angle,&segs->lndx,&segs->sndx,
&segs->loffset);
segs++;
bcase SSECTS: /* SSECTORS */
sscanf(str,"%*d %4hx %4hx",&ssecs->count,&ssecs->sndx);
ssecs++;
bcase NODES: /* NODES */
sscanf(str,"%*d \
%4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx %4hx",
&nodes->x,&nodes->y,&nodes->xdel,&nodes->ydel,
&nodes->rymax,&nodes->rymin,&nodes->rxmin,&nodes->rxmax,
&nodes->lymax,&nodes->lymin,&nodes->lxmin,&nodes->lxmax,
&nodes->nndx[0],&nodes->nndx[1]);
nodes++;
bcase SECTS: /* SECTORS */
sscanf(str,"%*d %4hx %4hx %8c %8c %4hx %4hx %4hx",
§s->floor_ht,§s->ceil_ht,sects->floor_desc,
sects->ceil_desc,§s->light_lvl,§s->property,
§s->line_tag);
while (sects->floor_desc[min(8,strlen(sects->floor_desc))-1] == ' ')
sects->floor_desc[min(8,strlen(sects->floor_desc))-1] = '\0';
while (sects->ceil_desc[min(8,strlen(sects->ceil_desc))-1] == ' ')
sects->ceil_desc[min(8,strlen(sects->ceil_desc))-1] = '\0';
sects++;
}
k = str[0] != '%';
}
winfo->ep++; winfo->mp++;
return TRUE;
}
/******************************************************************************
ROUTINE: patch_write(oinfo,winfo)
WRITTEN BY: Robert Fenske, Jr.
CREATED: May 1994
DESCRIPTION: This routine writes a VERDA patch file. Only one
level's data is stored in a patch file.
******************************************************************************/
#if defined(ANSI_C)
boolean patch_write(register WAD_INFO *oinfo, register WAD_INFO *winfo)
#else
boolean patch_write(oinfo,winfo)
register WAD_INFO *oinfo, *winfo;
#endif
{
DOOM_THING *things = (DOOM_THING *)winfo->data[THINGS];
DOOM_LINE *lines = (DOOM_LINE *)winfo->data[LINES];
DOOM_SIDE *sides = (DOOM_SIDE *)winfo->data[SIDES];
DOOM_VERT *verts = (DOOM_VERT *)winfo->data[VERTS];
DOOM_SEGS *segs = (DOOM_SEGS *)winfo->data[SEGS];
DOOM_SSECTOR *ssecs = (DOOM_SSECTOR *)winfo->data[SSECTS];
DOOM_NODE *nodes = (DOOM_NODE *)winfo->data[NODES];
DOOM_SECTOR *sects = (DOOM_SECTOR *)winfo->data[SECTS];
register int k;
fprintf(oinfo->fp,"%d %d %d %4.2f\r\n",
--winfo->ep,--winfo->mp,THINGS,winfo->ver);
for (k = 0; k < winfo->count[THINGS]; k++)
fprintf(oinfo->fp,"%03d %04x %04x %03d %04x %02x\r\n",k,
(ushort)things[k].x,(ushort)things[k].y,things[k].angle,
things[k].item,things[k].flag);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,LINES,winfo->ver);
for (k = 0; k < winfo->count[LINES]; k++)
fprintf(oinfo->fp,"%03d %04x %04x %04x %04x %04x %04x %04x\r\n",k,
lines[k].fndx,lines[k].tndx,
(ushort)lines[k].flag,(ushort)lines[k].action_flag,
(ushort)lines[k].sect_tag,
(ushort)lines[k].rsidndx,(ushort)lines[k].lsidndx);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,SIDES,winfo->ver);
for (k = 0; k < winfo->count[SIDES]; k++)
fprintf(oinfo->fp,"%03d %04x %04x %-8.8s %-8.8s %-8.8s %03x\r\n",k,
(ushort)sides[k].image_xoff,(ushort)sides[k].image_yoff,
sides[k].lwall,sides[k].uwall,sides[k].nwall,sides[k].sectndx);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,VERTS,winfo->ver);
for (k = 0; k < winfo->count[VERTS]; k++)
fprintf(oinfo->fp,"%03d %04x %04x\r\n",k,
(ushort)verts[k].x,(ushort)verts[k].y);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,SEGS,winfo->ver);
for (k = 0; k < winfo->count[SEGS]; k++)
fprintf(oinfo->fp,"%03d %04x %04x %04x %04x %04x %04x\r\n",k,
segs[k].fndx,segs[k].tndx,(ushort)segs[k].angle,
segs[k].lndx,segs[k].sndx,segs[k].loffset);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,SSECTS,winfo->ver);
for (k = 0; k < winfo->count[SSECTS]; k++)
fprintf(oinfo->fp,"%03d %04x %04x\r\n",k,
ssecs[k].count,ssecs[k].sndx);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,NODES,winfo->ver);
for (k = 0; k < winfo->count[NODES]; k++)
fprintf(oinfo->fp,"%03d \
%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\r\n",k,
(ushort)nodes[k].x,(ushort)nodes[k].y,
(ushort)nodes[k].xdel,(ushort)nodes[k].ydel,
(ushort)nodes[k].rymax,(ushort)nodes[k].rymin,
(ushort)nodes[k].rxmin,(ushort)nodes[k].rxmax,
(ushort)nodes[k].lymax,(ushort)nodes[k].lymin,
(ushort)nodes[k].lxmin,(ushort)nodes[k].lxmax,
(ushort)nodes[k].nndx[0],(ushort)nodes[k].nndx[1]);
fprintf(oinfo->fp,"%%\r\n%d %d %d %4.2f\r\n",
winfo->ep,winfo->mp,SECTS,winfo->ver);
for (k = 0; k < winfo->count[SECTS]; k++)
fprintf(oinfo->fp,"%03d %04x %04x %-8.8s %-8.8s %04x %04x %04x\r\n",k,
(ushort)sects[k].floor_ht,(ushort)sects[k].ceil_ht,
sects[k].floor_desc,sects[k].ceil_desc,
sects[k].light_lvl,sects[k].property,(ushort)sects[k].line_tag);
return TRUE;
}
/******************************************************************************
ROUTINE: wad_open(file,input,rewrite)
WRITTEN BY: Robert Fenske, Jr.
CREATED: June 1994
DESCRIPTION: This routine opens the specified file. The file is
created if input and rewrite are FALSE. If the open
fails for any reason a NULL is returned, otherwise an
information block is allocated for the file. The file
is identified as either a (P/I)WAD file or a VERDA
patch file. If the file is a (P/I)WAD file, then the
directory is read. The resource directory is held in
two locations--one for modification and one to preserve
the original directory. The address of the information
block is returned.
******************************************************************************/
#if defined(ANSI_C)
WAD_INFO *wad_open(char *file, boolean input, boolean rewrite)
#else
WAD_INFO *wad_open(file,input,rewrite)
char *file;
boolean input, rewrite;
#endif
{
register FILE *fp;
register WAD_INFO *winfo;
register int e;
fp = fopen(file,input?"rb":rewrite?"r+b":"wb");
if (fp == NULL) /* oops */
return NULL;
winfo = blockmem(WAD_INFO,1);
if (input || rewrite) {
rewind(fp);
fread((char *)&winfo->head,sizeof winfo->head,1,fp);
if (strncmp(winfo->head.ident,"PWAD",4) == 0 ||
strncmp(winfo->head.ident,"IWAD",4) == 0) {
winfo->type = 1; /* it's a (I/P)WAD */
winfo->head.count = bswapl(winfo->head.count);
winfo->head.offset = bswapl(winfo->head.offset);
}else {
rewind(fp);
if (3 == fscanf(fp," %d %d %*d %lf",&winfo->ep,&winfo->mp,&winfo->ver)) {
winfo->type = 2; /* it's a patch file */
winfo->head.count = ALL;
}else /* it's illegal */
memset(&winfo->head,0,sizeof(winfo->head));
}
winfo->origdir = blockmem(DIR_ENTRY,winfo->head.count);
winfo->dir = blockmem(DIR_ENTRY,winfo->head.count);
winfo->data = blockmem(char *,winfo->head.count);
winfo->changed = blockmem(boolean,winfo->head.count);
winfo->count = blockmem(long,winfo->head.count);
if (winfo->type == 1) { /* it's a WAD file */
rewind(fp);
fseek(fp,winfo->head.offset,0); /* read directory */
fread((char *)winfo->origdir,sizeof(*winfo->origdir),
(int)winfo->head.count,fp);
}else if (winfo->type == 2) { /* it's a patch file */
if (++winfo->ep != 4)
sprintf(winfo->origdir[MAINS].name,"E%dM%d",winfo->ep,++winfo->mp);
else
sprintf(winfo->origdir[MAINS].name,"MAP%02d",++winfo->mp);
for (e = 1; e < ALL; e++)
blockcopy(winfo->origdir[e].name,mapresrc[e],
sizeof winfo->origdir[e].name);
}
for (e = 0; e < winfo->head.count; e++) {
winfo->dir[e] = winfo->origdir[e];
winfo->dir[e].offset =
winfo->origdir[e].offset = bswapl(winfo->origdir[e].offset);
winfo->dir[e].nbytes =
winfo->origdir[e].nbytes = bswapl(winfo->origdir[e].nbytes);
}
}
winfo->fp = fp;
return winfo;
}
/******************************************************************************
ROUTINE: wad_read(winfo,entry,resources_needed)
WRITTEN BY: Robert Fenske, Jr.
CREATED: May 1994
DESCRIPTION: This routine reads a WAD file. resources_needed governs
which resources from the level are actually read.
******************************************************************************/
#if defined(ANSI_C)
boolean wad_read(register WAD_INFO *winfo, int entry, long resources_needed)
#else
boolean wad_read(winfo,entry,resources_needed)
register WAD_INFO *winfo;
int entry;
long resources_needed;
#endif
{
register int i;
if (winfo == NULL ||
winfo->fp == NULL) return FALSE; /* can't do if invalid */
if (winfo->type == 2)
return patch_read(winfo,entry,resources_needed);/* do patch file */
if (winfo->head.count <= entry) /* can't read beyond count */
return FALSE;
for (i = 0; i < sizeof(resources_needed)*8; i++) {
if (resources_needed & (1L<<i)) { /* get requested resources */
blockfree(winfo->data[entry+i]);
winfo->data[entry+i] = blockmem(char,winfo->origdir[entry+i].nbytes);
fseek(winfo->fp,winfo->origdir[entry+i].offset,0);
fread(winfo->data[entry+i],1,(int)winfo->origdir[entry+i].nbytes,
winfo->fp);
#if defined(BSWAP)
wad_bswap(winfo,entry+i);
#endif
winfo->count[entry+i] = resource_count(&winfo->origdir[entry+i]);
}
}
return TRUE;
}
/******************************************************************************
ROUTINE: wad_write(oinfo,winfo)
WRITTEN BY: Robert Fenske, Jr.
CREATED: May 1994
DESCRIPTION: This routine writes a WAD file. If oinfo has a
directory then the input file is being rewritten with
the new data; otherwise, a new file is written. The
resources are written out in reverse order; this easily
handles the case where the input file is being
rewritten and some of the resources have grown in size.
Also in the rewrite case, if a resource is smaller than
before, it is marked with the new smaller size but the
following resources are not "shifted down". Thus there
will be some parts of the file that will be unused.
******************************************************************************/
#if defined(ANSI_C)
boolean wad_write(register WAD_INFO *oinfo,register WAD_INFO *winfo)
#else
boolean wad_write(oinfo,winfo)
register WAD_INFO *oinfo, *winfo;
#endif
{
long dir_offset; /* new directory offset */
char *buf; /* temporary data buffer */
register int e;
if (oinfo == NULL ||
oinfo->fp == NULL) return FALSE; /* can't do if invalid */
if (oinfo->type == 2)
return patch_write(oinfo,winfo); /* do patch file */
winfo->dir[0].offset = sizeof winfo->head;
for (e = 1; e < winfo->head.count; e++) { /* compute new directory */
if (oinfo->dir == NULL || winfo->origdir[e-1].offset == 0)
winfo->dir[e].offset = winfo->dir[e-1].offset + winfo->dir[e-1].nbytes;
else
winfo->dir[e].offset = winfo->dir[e-1].offset +
max(winfo->dir[e-1].nbytes,
winfo->origdir[e].offset-
winfo->origdir[e-1].offset);
}
for (e = winfo->head.count-1; e >= 0; e--) { /* write resources */
if (winfo->changed[e] || winfo->type == 2) {/* write new data */
if (winfo->data[e] != NULL) {
#if defined(BSWAP)
wad_bswap(winfo,e);
#endif
fseek(oinfo->fp,winfo->dir[e].offset,0);
fwrite(winfo->data[e],1,(int)winfo->dir[e].nbytes,oinfo->fp);
blockfree(winfo->data[e]);
winfo->data[e] = NULL;
}
}else if (oinfo->dir == NULL ||
winfo->origdir[e].offset != winfo->dir[e].offset) {
buf = blockmem(char,winfo->origdir[e].nbytes);
fseek(winfo->fp,winfo->origdir[e].offset,0);
fread(buf,sizeof(*buf),(int)winfo->origdir[e].nbytes,winfo->fp);
fseek(oinfo->fp,winfo->dir[e].offset,0);
fwrite(buf,sizeof(*buf),(int)winfo->origdir[e].nbytes,oinfo->fp);
blockfree(buf);
}
}
dir_offset = winfo->dir[winfo->head.count-1].offset +
winfo->dir[winfo->head.count-1].nbytes;
for (e = 0; e < winfo->head.count; e++) {
winfo->dir[e].offset = bswapl(winfo->dir[e].offset);
winfo->dir[e].nbytes = bswapl(winfo->dir[e].nbytes);
}
fseek(oinfo->fp,dir_offset,0); /* write new directory */
fwrite((char *)winfo->dir,sizeof(*winfo->dir),(int)winfo->head.count,
oinfo->fp);
for (e = 0; e < winfo->head.count; e++) {
winfo->dir[e].offset = bswapl(winfo->dir[e].offset);
winfo->dir[e].nbytes = bswapl(winfo->dir[e].nbytes);
}
if (oinfo->dir != NULL)
blockcopy((char *)winfo->origdir,(char *)winfo->dir,/* this is now */
winfo->head.count*sizeof(winfo->dir[0]));/* original directory */
if (winfo->type == 2) blockcopy(winfo->head.ident,"PWAD",4);
winfo->head.offset = bswapl(dir_offset);
winfo->head.count = bswapl(winfo->head.count);
fseek(oinfo->fp,0L,0); /* write new header */
fwrite((char *)&winfo->head,sizeof(winfo->head),1,oinfo->fp);
winfo->head.offset = bswapl(dir_offset);
winfo->head.count = bswapl(winfo->head.count);
return TRUE;
}
/******************************************************************************
ROUTINE: wad_close(winfo)
WRITTEN BY: Robert Fenske, Jr.
CREATED: June 1994
DESCRIPTION: This routine closes the specified file and it frees
the associated memory.
******************************************************************************/
#if defined(ANSI_C)
void wad_close(register WAD_INFO *winfo)
#else
void wad_close(winfo)
register WAD_INFO *winfo;
#endif
{
if (winfo != NULL) {
if (winfo->fp != NULL) (void)fclose(winfo->fp);
blockfree(winfo->dir); /* done with these */
blockfree(winfo->origdir);
blockfree(winfo->data);
blockfree(winfo->changed);
blockfree(winfo->count);
blockfree(winfo);
}
}